package com.chen.longchain4jdemo.config;

import com.chen.longchain4jdemo.aiservice.ConsultantService;
import com.chen.longchain4jdemo.reposititory.RedisChatMemoryStore;
//import dev.langchain4j.community.store.embedding.redis.RedisEmbeddingStore;
import dev.langchain4j.community.store.embedding.redis.RedisEmbeddingStore;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.loader.ClassPathDocumentLoader;
import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.internal.OpenAiClient;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import io.netty.channel.ChannelOption;
import io.netty.resolver.DefaultAddressResolverGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.context.annotation.Primary;
import reactor.netty.http.client.HttpClient;

import java.util.List;

@Configuration
public class CommonConfig {

    @Autowired
    RedisChatMemoryStore redisChatMemoryStore;

    @Autowired
    EmbeddingModel embeddingModel;

    @Autowired
    RedisEmbeddingStore redisEmbeddingStore;

//    @Autowired
//    private OpenAiChatModel openAiChatModel;

//    @Bean
//    public ConsultantService consultantService() {
//        return AiServices.builder(ConsultantService.class)
//                .chatModel(openAiChatModel)
//                .build();
//    }

    /**
     * 构建ChatMemoryProvider对象用于会画存储
     *
     * @return
     */
    @Bean
    public ChatMemoryProvider chatMemoryProvider() {
        return new ChatMemoryProvider() {
            @Override
            public ChatMemory get(Object memoryId) {
                return MessageWindowChatMemory.builder()
                        .id(memoryId)
                        .maxMessages(20)
                        .chatMemoryStore(redisChatMemoryStore)
                        .build();
            }
        };
    }

    /**
     * 构建向量数据库操作对象EmbeddingStore
     *
     * @return
     */
    @Bean
    @Primary
    public EmbeddingStore store() {
        // 1.加载文档进内存
        // 加载文档的时候指定解析器
        // List<Document> documentList = ClassPathDocumentLoader.loadDocuments("content");
        List<Document> documentList = ClassPathDocumentLoader.loadDocuments("content", new ApachePdfBoxDocumentParser());

        // 2.构建向量数据库操作对象 操作的是内存版本的向量数据库
//         InMemoryEmbeddingStore store = new InMemoryEmbeddingStore();
        // 构建文档分割器对象
        DocumentSplitter documentSplitter = DocumentSplitters.recursive(500, 100);

        // 3.构建一个EmbeddingStoreIngestor对象，完成文本数据切割、向量化、存储
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
//                .embeddingStore(store)
                .documentSplitter(documentSplitter)
                .embeddingModel(embeddingModel)// 配置向量模型
                .embeddingStore(redisEmbeddingStore)// 配置向量数据库操作对象
                .build();
        // 4.读取文档
        ingestor.ingest(documentList);
//        return store;
        return redisEmbeddingStore;
    }

    @Bean
//    public ContentRetriever contentRetriever(EmbeddingStore embeddingStore) {
    public ContentRetriever contentRetriever() {
        // 我自己写了一个 EmbeddingStore的Bean，但是LangChain4j依赖自带了一个EmbeddingStore的Bean，Springboot会用谁的?
        // System.out.println(embeddingStore.getClass().getName());
        return EmbeddingStoreContentRetriever.builder()
//                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)// 配置向量模型
                .embeddingStore(redisEmbeddingStore) // 配置向量数据库操作对象
                .minScore(0.6)
                .maxResults(3)
                .build();
    }
}
